package com.triple.interviewexpert.aop;

import com.jd.platform.hotkey.client.callback.JdHotKeyStore;
import com.triple.interviewexpert.annotation.HotKeyCache;
import com.triple.interviewexpert.common.BaseResponse;
import com.triple.interviewexpert.common.ErrorCode;
import com.triple.interviewexpert.constant.HotKeyConstant;
import com.triple.interviewexpert.exception.ThrowUtils;
import com.triple.interviewexpert.model.dto.questionBank.QuestionBankQueryRequest;
import com.triple.interviewexpert.model.vo.QuestionVO;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class HotKeyAspect {
    @Around("@annotation(hotKeyCache)")
    public Object around(ProceedingJoinPoint joinPoint, HotKeyCache hotKeyCache) throws Throwable {
        String prefix = hotKeyCache.keyPrefix();
        int paramIndex = hotKeyCache.keyParamIndex();
        // 生成key
        Object[] args = joinPoint.getArgs();
        ThrowUtils.throwIf(paramIndex < 0 || paramIndex >= args.length, ErrorCode.PARAMS_ERROR);
        Object param = args[paramIndex];
        long id;
        if (prefix.equals(HotKeyConstant.QUESTION_HOT_KEY)) {
            id = (long) param;
            ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        } else {
            ThrowUtils.throwIf(param == null, ErrorCode.PARAMS_ERROR);
            QuestionBankQueryRequest questionBankQueryRequest = (QuestionBankQueryRequest) param;
            id = questionBankQueryRequest.getId();
            ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        }
        String key = prefix + id;
        // 判断是否是hotkey, 阈值为5秒内10次
        if (JdHotKeyStore.isHotKey(key)) {
            // 从本地缓存中获取缓存值, 如果缓存中有值, 直接返回缓存的值
            Object cachedBaseResponse = JdHotKeyStore.get(key);
            if (cachedBaseResponse != null) {
                // 直接返回就行, 不用类型转换, 因为下面的set直接给缓存的BaseResponse
                return cachedBaseResponse;
            }
        }
        // 没有缓存, 走方法查数据库
        Object proceed = joinPoint.proceed();

        // 不缓存伪造的 answer 数据
        if (isSensitiveOrFakeAnswer(proceed)) {
            return proceed;
        }

        // 设置本地缓存, 缓存直接为BaseResponse
        // 第10次进来, 不是hotkey, 无缓存
        // 第11次进来, 是hotkey, 设置缓存
        // 第12次进来, 是hotkey, 有缓存
        JdHotKeyStore.smartSet(key, proceed);
        return proceed;
    }

    private boolean isSensitiveOrFakeAnswer(Object result) {
        if (!(result instanceof BaseResponse)) {
            return false;
        }
        BaseResponse<?> response = (BaseResponse<?>) result;
        if (!(response.getData() instanceof QuestionVO)) {
            return false;
        }
        QuestionVO vo = (QuestionVO) response.getData();
        return vo.getAnswer().equals("请先登录才能获取答案");
    }
}
